
#ifndef HASHTABLE_H_
#define HASHTABLE_H_

#include <iostream>
#include <vector>
#include <sstream>
#include "../../CapaFisica/BlockedFile.h"

#define SIZE_BUFFER 512
#define ARCH_TABLA_EXT "tbl"

using namespace std;

class HashTable {
private:
	string nombre;
	BlockedFile archivoHash;
	vector<int> bufferBloques;
	int cantidadElementosBuffer;
	int posInicioBuffer;

	/*****Metodos de utilidad**********/
	int calcularPosicion(int pos, int tamanioDispersion, bool up);

	//Inicializa el buffer de la tabla en -1 en las posiciones.
	void inicializarBuffer();

	//Genera buffer de posiciones de bloques del archivo entre la posInicial y el size del buffer.
	void armarBuffer(int posInicial);

	/**
	 * Escribe el buffer en archivo.
	 * append: Si esta en true escribe al final del archivo , de lo contrario actualiza buffer en disco.
	 */
	void escribirBuffer(bool append, BlockedFile * archivo);

	/**
	 * Escribe el buffer en disco.
	 * append: Si esta en true escribe al final del archivo , de lo contraria actualiza buffer en disco.
	 */
	void escribirBuffer(bool append);

	/**
	 * Verifica si la posicion esta en buffer
	 */
	bool estaPosicionEnBuffer(int posicionTabla);

	/**
	 * Devuelve el tamaño de la porcion de tabla en buffer
	 */
	int getTamanioTablaBuffer();

	/**
	 * verifica si la tabla esta espejada
	 */
	bool isTablaEspejada();

	/**
	 * Trunca la tabla cuando esta espejada
	 */
	void truncarTabla();

public:
	HashTable(string path);
	~HashTable();

	/**
	 * Hashea la clave y devuelve la posicion que corresponde en la tabla segun la clave ingresada
	 */
	int getHash(int clave);
	/**
	 * Devuelve el path del archivo de la tabla.
	 */
	string getPath();
	/**
	 * Setea el id del bucket en la posicion de la tabla indicada.
	 *
	 */
	void setIdBucket(int posicionTabla,int idBucket);

	/**
	 * Obtiene el id del bucket de la posicion de la tabla solicitada.
	 */
	int getIdBucket(int posicionTabla);


	/**
	 * Devuelve el bloque correspondiente para el registro segun la clave ingresada
	 */
	int obtenerIdBucket(int clave);
	/**
	 * Calcula el tamaño de la tabla
	 */
	int getTamanioTabla();

	/**
	 * Duplica la tabla cuando se crea un bloque nuevo
	 * Parametros de entrada:
	 * pos: numero de posicion de la tabla que devolvio la función Hash, donde el bloque saturó.
	 * idBloqueNuevo: el id del nuevo bloque que se creo
	 */
	void duplicar(int pos, int idBloqueNuevo);
	/**
	 * Libera un bloque
	 * Parametros: la posicion del bloque en la tabla y el tamanio de Dispersion del bloque a liberar.
	 * Retorna el idBucket que se reemplazo por el liberado si se pudo liberar , de lo contrario se devuelve -1.
	 */
	int liberarBloque(int tamanioDispersion, int pos);

};

#endif /* HASHTABLE_H_ */
